#pragma once

#include "Model.h"

// lib
#include <glm/gtc/matrix_transform.hpp>
// std
#include <memory>
#include <unordered_map>

namespace vkengine {

    struct RigidBody2dComponent {
        glm::vec2 velocity;
        float mass{ 1.0f };
    };

    struct TransformComponent {
        glm::vec3 translation{};
        glm::vec3 scale{ 1.f, 1.f, 1.f };
        glm::vec3 rotation{};

        // Matrix corrsponds to Translate * Ry * Rx * Rz * Scale
        // Rotations correspond to Tait-bryan angles of Y(1), X(2), Z(3)
        // https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
        glm::mat4 Mat4();
        glm::mat3 NormalMatrix();
    };

    struct PointLightComponent {
        float lightIntensity = 1.0f;
    };
    class GameObject {
    public:
        using id_t = unsigned int;
        using Map = std::unordered_map<id_t, GameObject>;

        static GameObject CreateGameObject() {
            static id_t currentId = 0;
            return GameObject{ currentId++ };
        }

        static GameObject MakePointLight(
            float intensity = 10.f, float radius = 0.1f, glm::vec3 color = glm::vec3(1.f));

        GameObject(const GameObject&) = delete;
        GameObject& operator=(const GameObject&) = delete;
        GameObject(GameObject&&) = default;
        GameObject& operator=(GameObject&&) = default;

        id_t GetId() { return m_id; }

    public:
        
        glm::vec3 color{};
        TransformComponent transform{};
        RigidBody2dComponent rigidBody2d{};
        // Optional pointer components
        std::shared_ptr<Model> model{};
        std::unique_ptr<PointLightComponent> pointLight = nullptr;

    private:
        GameObject(id_t objId) : m_id{ objId } {}

        id_t m_id;
    };
}